package com.jxb.test;

import java.util.Random;

/**
 * 漏桶算法
 * QPS达到水桶总量就会限流
 * 一大批请求过来，会先进入漏桶，当剩余水量大于漏桶总量（请求数大于指定的阈值），就会限流
 * 若要提高并发量，在机器支持的情况下，可以先提高漏桶总量和系统请求速度，也就是流水速率
 * 特点：系统处理请求的速度是固定的，一大批请求过来会匀速处理，请求数达到阈值，剩余的请求会被拦截，起到限流的作用
 */
public class LeakyBucket {

    private static Long water = 0L;//剩余水量
    private static Long rate = 50L;//流水速率-系统处理请求的速度（这里指定每秒钟处理50个请求）
    private static Long capacity = 100L;//水桶总量

    public static void main(String[] args) {
        //系统执行任务请求
        new Thread(new Runnable() {
            @Override
            public void run() {
                doTask();
            }
        }).start();

        //模拟高并发场景
        while (true) {
            try {
                Thread.sleep(new Random().nextInt(15));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //判断是否限流
            if (!limit()) {
                System.out.println("已限流... ...");
            }else {
                water++;
            }
        }
    }

    private static void doTask() {
        for (;;) {
            //根据指定速率来获取water，每次睡眠1s
            water = Math.max(0,capacity - rate);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


    public static boolean limit() {
        if ((water + 1) > capacity) {
            return false;
        }
        return true;
    }

}
